package com.fq.ioc.reflect;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fq.ioc.annotation.processor.BeanProcessor;
import com.fq.ioc.constant.CommonConstant;
import com.fq.ioc.json.JsonParse;
import com.fq.ioc.utils.PackageScanUtils;
import com.fq.ioc.xml.XmlParse;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Element;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author jifang
 * @since 16/1/6下午1:52.
 */
public class ObjectPoolBuilder {

    private static ObjectPool OBJECTPOOL;

    private static class ConcreteObjectPool extends ObjectPool {
        protected ConcreteObjectPool(Map<String, Object> pool) {
            super(pool);
        }
    }

    // 创建一个对象池的实例(保证线程安全)
    private static void initSingletonPool() {
        if (OBJECTPOOL == null) {
            synchronized (ObjectPool.class) {
                if (OBJECTPOOL == null) {
                    OBJECTPOOL = new ConcreteObjectPool(new ConcurrentHashMap<String, Object>());
                }
            }
        }
    }

    // 根据注解来初始化对象池
    private static ObjectPool initWithAnnotation(String config) {
        // 初始化pool
        initSingletonPool();
        try {
            JSONArray packages = JsonParse.getPackages(config);
            for (int i = 0; packages != null && i < packages.size(); ++i) {
                JSONObject packageName = packages.getJSONObject(i);
                List<String> classNames = PackageScanUtils.
                        scanPackage(packageName.getString(CommonConstant.PACKAGE));
                for (String className : classNames) {
                    BeanProcessor.processObject(className);
                }
            }
            return OBJECTPOOL;
        } catch (IOException | ClassNotFoundException | NoSuchMethodException |
                InvocationTargetException | InstantiationException |
                IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    // 根据XML配置文件来初始化对象池
    @SuppressWarnings("unchecked")
    private static ObjectPool initWithXml(String config) {
        initSingletonPool();

        try {
            Element beans = XmlParse.parseBeans(config);
            Iterator beanIter = beans.elementIterator();
            while (beanIter.hasNext()) {
                Element bean = (Element) beanIter.next();
                XmlParse.processObject(bean, bean.elements());
            }
        } catch (ClassNotFoundException | NoSuchFieldException |
                InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        return OBJECTPOOL;
    }

    // 仅初始化对象池
    private static ObjectPool initDefault() {
        // 初始化pool
        initSingletonPool();
        return OBJECTPOOL;
    }

    public static ObjectPool init(String config) {
        if (StringUtils.isNoneBlank(config)) {
            if (config.endsWith(".json")) {
                return initWithAnnotation(config);
            } else if (config.endsWith(".xml")) {
                return initWithXml(config);
            } else {
                throw new RuntimeException("need a configuration file json or xml");
            }
        } else {
            return initDefault();
        }
    }
}
